﻿using System;
using BITS.PreCompiler.CSharp.Syntax;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace BITS.PreCompiler.CSharp.Tests.Syntax
{
    [TestClass]
    public class TestInterface
    {
        [TestMethod]
        public void Create_Interface()
        {
            var @interface = new Interface("IMyClass");

            var expectet = Comparer.Create_Interface();
            var actual   = @interface.ToString();

            Assert.AreEqual(expectet, actual);
            Console.WriteLine(actual);
        }

        [TestMethod]
        public void Create_Interface_With_String_Members()
        {
            var @interface = new Interface("IMyClass")
            {
                @"int TestPropertyA { get; set; }",
                
                @"string TestPropertyB { get; set; }",
                
                @"int TestMethodA()",
            };

            var expectet = Comparer.Create_Interface_With_String_Members();
            var actual   = @interface.ToString();

            Assert.AreEqual(expectet, actual);
            Console.WriteLine(actual);
        }

        [TestMethod]
        public void Create_Interface_With_Methods()
        {
            var typeA = new Interface("TypeA");

            var @private_MyClass_MethodA = new InterfaceMethod(typeA, identifier: "MethodA");
            var @private_MyClass_MethodB = new InterfaceMethod(@return: "NewClass", identifier: "MethodA");

            var @interface = new Interface("IMyClass")
            {
                @private_MyClass_MethodA,
                @private_MyClass_MethodB,
            };

            var expectet = Comparer.Create_Interface_With_Methods();
            var actual   = @interface.ToString();

            Assert.AreEqual(expectet, actual);
            Console.WriteLine(actual);
        }

        [TestMethod]
        public void Create_Interface_With_Properties()
        {
            var typeA = new Interface("TypeA");

            var @private_MyClass_PropertyA = new InterfaceProperty(typeA, identifier: "PropertyA")
                .WithAuto();

            var @private_MyClass_PropertyB = new InterfaceProperty(@return: "NewClass", identifier: "PropertyA")
                .WithAuto();

            var @interface = new Interface("IMyClass")
            {
                @private_MyClass_PropertyA,
                @private_MyClass_PropertyB,
            };

            var expectet = Comparer.Create_Interface_With_Properties();
            var actual   = @interface.ToString();

            Assert.AreEqual(expectet, actual);
            Console.WriteLine(actual);
        }

        [TestMethod]
        public void Create_Interface_With_Properties_And_Methods()
        {
            var typeA = new Interface("TypeA");

            var @private_MyClass_PropertyA = new InterfaceProperty(typeA, identifier: "PropertyA")
                .WithAuto();

            var @private_MyClass_PropertyB = new InterfaceProperty(@return: "NewClass", identifier: "PropertyB")
                .WithAuto();

            var @private_MyClass_MethodA = new InterfaceMethod(typeA, identifier: "MethodA");
            var @private_MyClass_MethodB = new InterfaceMethod(@return: "NewClass", identifier: "MethodB");

            var @interface = new Interface("IMyClass")
            {
                @private_MyClass_PropertyA,
                @private_MyClass_PropertyB,

                @private_MyClass_MethodA,
                @private_MyClass_MethodB,
            };

            var expectet = Comparer.Create_Interface_With_Properties_And_Methods();
            var actual   = @interface.ToString();

            Assert.AreEqual(expectet, actual);
            Console.WriteLine(actual);
        }

        [TestMethod]
        public void Create_Class_With_String_Members_And_Strong_Typed_Members()
        {
            var typeA = new Interface("TypeA");

            var @interface = new Interface("IMyClass")
            {
                @"public int TestPropertyA { get; set; }",
                
                @"public string TestPropertyB { get; set; }",

                new InterfaceProperty(@return: "NewClass", identifier: "PropertyC")
                    .WithAuto(),

                new InterfaceProperty(@return: "NewClass", identifier: "PropertyD")
                {
                    @"get;",
                    @"set;",
                },
                
                @"public int TestMethodA();",

                new InterfaceMethod(typeA, identifier: "MethodB"),
            };

            var expectet = Comparer.Create_Interface_With_String_Members_And_Strong_Typed_Members();
            var actual   = @interface.ToString();

            Assert.AreEqual(expectet, actual);
            Console.WriteLine(actual);
        }


        public static class Comparer
        {
            public static String Create_Interface()
            {
                return
@"public interface IMyClass
{
}";
            }

            public static String Create_Interface_With_String_Members()
            {
                return
@"public interface IMyClass
{
    int TestPropertyA { get; set; }

    string TestPropertyB { get; set; }

    int TestMethodA();
}";
            }

            public static String Create_Interface_With_Methods()
            {
                return
@"public interface IMyClass
{
    TypeA MethodA();
    NewClass MethodA();
}";
            }

            public static String Create_Interface_With_Properties()
            {
                return
@"public interface IMyClass
{
    TypeA PropertyA { get; set; }

    NewClass PropertyA { get; set; }
}";
            }

            public static String Create_Interface_With_Properties_And_Methods()
            {
                return
@"public interface IMyClass
{
    TypeA PropertyA { get; set; }

    NewClass PropertyB { get; set; }

    TypeA MethodA();
    NewClass MethodB();
}";
            }

            public static String Create_Interface_With_String_Members_And_Strong_Typed_Members()
            {
                return
@"public interface IMyClass
{
    int TestPropertyA { get; set; }

    string TestPropertyB { get; set; }

    NewClass PropertyC { get; set; }

    NewClass PropertyD { get; set; }

    int TestMethodA();
    TypeA MethodB();
}";
            }
        }
    }
}
